<template>
	<view class="wrap">
		<!-- 搜索框 -->
		<view class="search">
			<view class="searchInput" @click="search">
				<u-icon name="search" color="#909399" :size="26"></u-icon>
				<text class="inputTxt">请输入搜索关键词</text>
			</view>
		</view>
		<!-- 加载效果 -->
		<block v-if="status=='loading'">
			<u-loadmore :status="status"></u-loadmore>
		</block>
		<!-- 滚动区域 -->
		<view v-else-if="status == 'nomore'" class="menuwrap">
			<!-- 左侧滚动区域：纵向滚动，开启滑动的动画效果：动态设置纵向滚动条在每次点击后的位置 -->
			<scroll-view scroll-y scroll-with-animation class="leftNav" :scroll-top="scrollTop">
				<view v-for="(item,index) in navList" :key="item.name" class="tabItem" @tap.stop="toggleMenu(index)">
					<text :class="['line',currentIndex==index ? 'active':'']">{{item.name}}</text>
				</view>
			</scroll-view>
			
			<!-- 右侧滚动区域：纵向滚动，开启滚动的动画效果 -->
			<scroll-view scroll-y scroll-with-animation class="rigthNav" :scroll-top="scrollRigthTop" @scroll="rigthScroll">
				<view class="pageView">
					<view class="section" v-for="(item,index) in navList" :key="item.name" :id="'item'+index">
						<view class="titel">
							<text>{{item.name}}</text>
						</view>
						<view class="aside">
							<!-- key不可重复 -->
							<view class="li" v-for="(val,i) in item.foods" :key="i">
								<image class="li-img" :src="val.icon"></image>
								<view class="li-name">{{val.name}}</view>
							</view>
						</view>
					</view>
				</view>
			</scroll-view>
		</view>
	</view>
</template>

<script>
import { apiClassfy } from '../../api/mock';
	export default {
		data() {
			return {
				navList : []	,//分类数据
				status : 'loading',
				currentIndex : 0,
				scrollTop : 0,		// 每次点击的滚动条位置变量，默认从第一个开始
				oldScrollTop : 0	,// 上一次点击的滚动条位置
				menuHeight : 0,		 // 整个左侧菜单的高度
				menuItemHeight : 0,	 // 左侧单个菜单的高度
				TopArr : [],		// 根据标签顺序，获取每个section的高度
				scrollRigthTop : 0,	// 右侧菜单高度
				timer : '', // 定时器
			}
		},
		onLoad() {
			this.getClassfy();
		},
		onReady() {
			// 当页面初次渲染完后，获取所有section的高度（右侧菜单的所有高度）
			this.getMenuItemTopDistance();
		},
		methods: {
			search(){
				uni.navigateTo({
					url:'/pages/search/search'
				})
			},
			/* 发起请求的函数 */
			getClassfy(){
				apiClassfy().then((res)=>{
					this.status = 'nomore';
					console.log(this.status);
					this.navList = [...res];
					console.log(this.navList);
				}).catch((err)=>{
					console.log(err);
				})
			},
			
			/* 工具函数：获取右侧每个子菜单的高度（到顶部的距离） */
			getMenuItemTopDistance(){
				new Promise((resolve)=>{
					let query =uni.createSelectorQuery();
					// 从所有section中获取每个节点的布局位置信息
					query.selectAll('.section').boundingClientRect((data)=>{
						if( !data.length ){
							setTimeout(()=>{
								this.getMenuItemTopDistance();
							},20)
							return;
						}
						// 遍历：获取每个section的top坐标，计算出距离第一个置顶的菜单距离
						data.forEach((item)=>{
							console.log(item.top);
							this.TopArr.push( item.top - data[0].top );
							resolve();
						})
					}).exec();
				})
			},
			
			/* 工具函数：获取指定菜单的整体高度以及单个标签的高度（标签设置为参数）：为了让toggleMenu做菜单的定位居中 */
			/* elClass：你想要获取的标签选择器名称 */
			/* dataVal参数：动态给不确定的data变量赋值 */
			getElRect( elClass , dataVal ){
				new Promise((resolve , reject)=>{
					// 获取当前传递过来的标签节点的对象
					let query =uni.createSelectorQuery().in(this);
					// 获取指定标签选择器的尺寸宽高
					query.select('.'+elClass).fields( {size:true} , (res)=>{
						/* 如果页面渲染加载较慢，有可能标签会在此时仍未获取成功 */
						if( !res ){
							setTimeout(()=>{
								// 过一段时间再次执行本函数即可
								this.getElRect(elClass);
							} , 20)
							return;
						}
						// 将this作为数组，将dataVal作为下标；根据需求，从res内获取所需信息
						this[dataVal] =res.height; //this.menuItemHeigh = 55;
						console.log(this[dataVal]);
					} ).exec();
				})
			},
			
			/* 切换左侧菜单；促使被点击的菜单居中显示（抛出最开始和最后的菜单） */
			async toggleMenu(index){
				// 重复点击
				if(index == this.currentIndex) return;
				//将上一次获取到的滚动条位置赋值给右侧滚动变量
				this.scrollRigthTop =this.oldScrollTop;
				// this.$nextTick()：将Dom更新更改时机：下一次数据更新之后，Dom更新之前
				this.$nextTick(function(){
					// 将本次点击的下标index，从section高度数组中获取对应的元素值并赋值给右侧滚动高度
					this.scrollRigthTop =this.TopArr[index];
					// 将本次点击的下标，赋值给下一次选中下表变量
					this.currentIndex =index;
					// 调用滚动动画计算过程
					this.leftMenuStatus(index);
				})
			},
			// 设置左侧菜单的滚动动画状态：居中菜单
			async leftMenuStatus( index ){
				// 将本次点击的下标，赋值给当前选择器样式判断变量
				this.currentIndex = index;
				// 如果两个菜单的高度都为0的情况下，表示菜单的高度并未获取
				if( this.menuHeight == 0 || this.menuItemHeight == 0 ){
					// 获取左侧菜单的高度
					await this.getElRect('leftNav' , 'menuHeight');
					// 获取单个菜单的高度
					await this.getElRect('tabItem' , 'menuItemHeight');
				}
				
				// 计算出当前所点击的菜单，需要将滚动条设置到哪个位置上
				this.scrollTop = index*this.menuItemHeight + this.menuItemHeight/2 - this.menuHeight/2;
				console.log(this.scrollTop);
			},
			/* 右侧滚动事件：触发左侧的动画效果 */
			async rigthScroll(e){
				// 将本次的滚动顶点坐标赋值给oldScrollTop
				this.oldScrollTop = e.detail.scrollTop;
				// 保险机制：当前事件调用工具函数之前，先判断工具函数的返回值/data数据是否已经有结果，那就需要再次执行工具函数
				if(this.TopArr.length == 0){
					await this.getMenuItemTopDistance();
				}
				if( !this.menuHeight ){
					await this.getElRect('leftNav' , 'menuHeight');
				}
				// 定时器：节流:节约整个逻辑操作
				this.timer = setTimeout(()=>{
					// 延迟定时器启动后，内部清空
					this.timer = null;
					let scollHeight = this.menuHeight / 2 + e.detail.scrollTop;
					// 遍历所有section菜单的高度
					for(let i=0; i<this.TopArr.length; i++){
						let height1 = this.TopArr[i];		//当前i的高度：女装section
						let height2 = this.TopArr[i+1];		//下一个i的高度：美食section
						// 还没到最后一个section 或者 滚动的中间点大于section的高度（滚动已经离开了当前菜单）同时 滚动的中间点小于下一个菜单（下一个菜单还没有滚动完）
						if( !height2 || scollHeight>=height1 && scollHeight < height2 ){
							this.leftMenuStatus(i);
							return;
						}
					}
					
				},100)
			}
		}
	}
</script>

<style lang="scss">
/* calc()：计算复杂的公式 ：计算根据设备屏幕尺寸计算出目标区域的自适应高度/宽度 */
.wrap{
	height: calc(93vh);
	display: flex;
	flex-direction: column;
	/* 进行条件编译 */
	/* #ifdef H5 */
	height: calc( 100vh - var(--window-top) );
	/* #endif */
}
/* 搜索框样式 */
.search{
	padding: 8px 20px;
	.searchInput{
		background-color: rgb(234, 234, 234);
		border-radius: 20px;
		display: flex;
		align-items: center;
		padding: 0 8px;
		.inputTxt{
			font-size: 14px;
			color: $u-tips-color;
			margin-left: 10px;
		}
	}
}
.menuwrap{
	background-color: white;
	display: flex;
	flex: 1;	//表示：在100vh的基础下，减去搜索框所占的高度，剩余高度由该标签继承
	overflow: hidden;	//清除掉页面的滚动条
	// 左侧
	.leftNav{
		width: 25%;
		// 高度百分百的前提是：父级标签有明确高度，100%与父级标签的高度一致
		height: 100%;
		.tabItem{
			height: 55px;
			background-color: #f6f6f6;
			box-sizing: border-box;	
			font-size: 13px;
			color: #444;
			font-weight: 400;
			.line{
				display: flex;
				align-items: center;
				justify-content: center;
				width: 100%;
				height: 100%;
				/* &表示当前所在区域的clas选择器.tabItem */
				&.active{
					color: #000;
					font-size: 14px;
					font-weight: 600;
					background-color: white;
					position: relative;
					
					//  ::before伪类：在指定标签之前添加的效果(不用标签包裹的)
					//  ::after伪类：在指定标签之后添加的效果
					&::before{
						content: "";
						position: absolute;
						height: 16px;
						left: 0;
						top: 19px;
						border: 2px solid #3c9cff;
					}
				}
			}
		}
	}
	.rigthNav{
		
		.pageView{
			padding: 8px;
			overflow: hidden;
			.section{
				margin-bottom: 15px;
				padding: 8px;
				border-radius: 4px;
				&:last-child{
					min-height: 100vh;
				}
				.title{
					font-size: 14px;
					color: #303133;
					font-weight: bold;
				}
				.aside{
					display: flex;
					flex-wrap: wrap;
					.li{
						width: 33.33333333%;
						display: flex;
						align-items: center;
						justify-content: center;
						flex-direction: column;
						margin-top: 10px;
						.li-img{
							width: 60px;
							height: 60px;
						}
						.li-name{
							font-weight: normal;
							font-size: 12px;
							color: #303133;
						}
					}
				}
			}
		}
	}
}
</style>